from flask import (
    Blueprint, request, url_for, redirect, render_template,
    flash,
)
from flask_login import current_user, login_required, logout_user, login_user

from blog import db, bcrypt
from blog.post.models import Post
from .forms import (
    ProfileForm, ResetRequestForm, PasswordResetForm,
    LoginForm, RegistrationForm,
)
from .models import User
from .utils import save_img, send_reset_email

auth = Blueprint('auth', __name__)


@auth.route('/profile', methods=['GET', 'POST'])
@login_required
def profile():
    """个人中心页面，如果用户没有登录直接访问该路由返回401 Unauthorized错误页面
    如果需要重定向到登录页面则需要指定login_view属性，如:
        login_manager.login_view = 'login'
    详细设置查看blog.__init__.py
    """
    form = ProfileForm()
    # 往表单自动填充个人数据
    if request.method == 'GET':
        form.username.data = current_user.username
        form.email.data = current_user.email
        # form.avatar.data = current_user.avatar

    if form.validate_on_submit():
        # 如果用户上传个人头像
        if form.avatar.data:
            current_user.avatar = save_img(form.avatar.data)

        current_user.username = form.username.data
        current_user.email = form.email.data
        db.session.commit()
        flash('个人数据更新成功！', category='success')
        return redirect(url_for('auth.profile'))

    avatar = url_for('static', filename=f'avatars/{current_user.avatar}')
    return render_template(
        'profile.html',
        title='个人中心',
        avatar=avatar,
        form=form
    )


@auth.route('/logout')
def logout():
    """退出"""
    logout_user()
    return redirect(url_for('main.index'))


@auth.route('/register', methods=['GET', 'POST'])
def register():
    """注册"""
    form = RegistrationForm()
    if form.validate_on_submit():
        hashed_password = bcrypt.generate_password_hash(form.password.data).decode()
        user = User(
            username=form.username.data,
            email=form.email.data,
            password=hashed_password
        )
        # 如果注册已经存在的用户名或者邮箱的时候抛出sqlalchemy.exc.IntegrityError异常
        # 解决方案: 为RegistrationForm添加定制验证钩子函数(validate_<fieldname>)
        db.session.add(user)
        db.session.commit()

        # category参数指定bootstrap的alert类别(如: success, info, warning)
        flash(f'用户创建成功，您现在可以登录', category='success')
        return redirect(url_for('auth.login'))
    return render_template('register.html', title='注册', form=form)


@auth.route('/login', methods=['GET', 'POST'])
def login():
    """登录"""
    # 如果用户已经登录，用户访问登录页面时重定向到主页
    if current_user.is_authenticated:
        return redirect(url_for('main.index'))

    form = LoginForm()
    if form.validate_on_submit():
        user = User.query.filter_by(email=form.email.data).first()
        if user and bcrypt.check_password_hash(user.password, form.password.data):
            # flask_login
            login_user(user, remember=form.remember_me.data)
            # 登录成功后，从哪里来回哪里去，如: http://127.0.0.1:5000/login?next=%2Fprofile
            # 会重定向到个人中心页面
            next_page = request.args.get('next')
            return redirect(next_page) if next_page else redirect(url_for('main.index'))
        else:  # 如果登录不成功
            flash('密码或邮箱错误', category='danger')
    return render_template('login.html', title='登录', form=form)


@auth.route('/user/<string:username>/')
def user_posts(username):
    """属于该用户的文章页面"""
    page = request.args.get('page', default=1, type=int)
    user = User.query.filter_by(username=username).first_or_404()
    # 排序-逆序
    posts = Post.query.filter_by(
        user=user).order_by(Post.created.desc()).paginate(page=page, per_page=5)  # 每頁五個
    return render_template('user_posts.html', title=f'{user.username}的文章', posts=posts, user=user)


@auth.route('/reset_password/<token>', methods=['GET', 'POST'])
def password_reset(token):
    """密码重置，显示两个密码输入框，让用户重置密码"""
    if current_user.is_authenticated:
        return redirect(url_for('main.index'))
    user = User.check_reset_token(token)
    if user is None:
        flash('无效连接(过期或者连接有误)，请重新发送邮件', category='warning')
        return redirect(url_for('auth.reset_request'))
    form = PasswordResetForm()
    if form.validate_on_submit():
        hashed_password = bcrypt.generate_password_hash(form.password.data).decode()
        # 更新密码
        user.password = hashed_password
        db.session.commit()
        flash('密码重置成功', category='success')
        return redirect(url_for('auth.login'))
    return render_template('password_reset.html', title='密码重置', form=form)


@auth.route('/reset_password', methods=['GET', 'POST'])
def reset_request():
    """用户忘记密码，通过发送邮箱进行密码重置"""
    # 用户不能在登录的时候进行密码重置
    if current_user.is_authenticated:
        return redirect(url_for('main.index'))
    form = ResetRequestForm()
    if form.validate_on_submit():
        user = User.query.filter_by(email=form.email.data).first()
        send_reset_email(user)
        flash(f'邮件发送成功！请查看您的邮箱({form.email.data})，根据指示进行密码重置', category='info')
        return redirect(url_for('main.index'))
    return render_template('reset_request.html', form=form, title='发送密码重置邮件')
